본문으로 건너뛰기

23.05.10

오늘 한 일

  • 알고리즘 문제 풀이
  • 바닐라 JS로 리액트 만들기 스터디 정리
    • 저번 주차에 만들었던 VirtualDOM에서 render phase와 commit phase 분리 노션 링크
  • 익스텐션 리팩토링
    • 모달 켜질 때 뒷 배경의 스크롤바가 사라져 layout shift 되는 문제 수정

알고리즘 문제 풀이


배열을 특정 값으로 초기화 하는 방법
```js
Array(배열 길이).fill(채울 값);

// or

Array.from({length: 배열 길이}, () => 채울 값);

10진수를 2진수로 변경했을 때 n자리로 유지하고 싶을 때

(10진수).toString(2).padStart(n, '0');

2진수로 된 문자열에서 '0'이면 공백, '1'이면 '#'으로 변경

(2진수로 된 문자열).replace(/0/g, ' ').replace(/1/g, '#');

// or

(2진수로 된 문자열).replace(/0|1/g, (match) => match === '0' ? ' ' : '#');


`single vertical bar`?
```js
a|b

a와 b를 각각 2진수로 변환 후, 각 자리수를 비교하여 둘 중 하나라도 1이면 1, 아니면 0으로 변환해준다.

그럼 이 문제를 한 줄로 클리어할 수 있다!!

const solution = (n, a, b) =>
a.map((a, i) => (a | b[i]).toString(2).padStart(n, 0).replace(/0/g, ' ').replace(/1/g, '#'));

정규표현식과 single vertical bar라는 개념을 알았다면 쉽게 풀 수 있는 문제였다.

익스텐션 리팩토링

기존에 useBodyScrollLock hook을 만들어서 사용했었는데, 모달 켜질 때 뒷 배경의 스크롤바가 사라져 layout shift 되는 문제가 있었다.

이 문제를 해결하기 위해 Modal이 켜지면 useEffect로 스타일을 바꾸고, Modal이 꺼지면 다시 원래 스타일로 바꾸는 방식으로 해결했다.

useEffect(() => {
document.body.style.cssText = `
position: fixed;
top: -${window.scrollY}px;
overflow-y: scroll;
width: 100%;`;
return () => {
const scrollY = document.body.style.top;
document.body.style.cssText = '';
window.scrollTo(0, parseInt(scrollY || '0', 10) * -1);
};
}, []);

원래 Modal 컴포넌트에서는 isOpen을 props로 받아서 구현했었는데, Modal 컴포넌트를 사용하는 쪽에서 isOpen을 관리하도록 수정했다.

그리고 Content.js에 Modal에 해당하는 코드를 ContentModal이라는 컴포넌트로 분리했다. 이 컴포넌트에 위의 useEffect 부분을 넣어서 Modal이 켜질 때 스타일을 바꾸고, 꺼질 때 원래 스타일로 바꾸도록 했다.

<Portal elementId="modal">
{isModalOpen && (
<ContentModal
ref={modalRef}
onClick={event => {
if (event.target === modalRef.current) setIsModalOpen(false);
}}
assignmentList={assignmentList}
courseList={courseList}
handleRefresh={handleRefresh}
/>
)}
</Portal>

Filter 컴포넌트도 리팩토링했다.

기존 코드

<Filter
value={selectedCourse}
onChange={setSelectedCourse}
hasBorder={false}
maxWidth="300px"

<Filter.Header className="text-[18px] font-bold" name={selectedCourse.name} />
<Filter.Modal pos="left">
{courseList.map(course => (
<Filter.Item key={course.id} item={course}>
{course.name}
</Filter.Item>
))}
</Filter.Modal>
</Filter>
<div className="flex gap-[16px]">
<Filter value={sortType} onChange={setSortType}>
<Filter.Header name={sortType} />
<Filter.Modal>
<Filter.Item item="마감일 순">마감일 순</Filter.Item>
<Filter.Item item="최신 순">최신 순</Filter.Item>
</Filter.Modal>
</Filter>
<Filter value={statusType} onChange={setStatusType}>
<Filter.Header name={statusType} />
<Filter.Modal>
<Filter.Item item="진행중인 과제">진행중인 과제</Filter.Item>
<Filter.Item item="모든 과제">모든 과제</Filter.Item>
</Filter.Modal>
</Filter>
</div>

리팩토링 후

<Filter
value={selectedCourse}
onChange={setSelectedCourse}
hasBorder={false}
maxWidth="300px"

<Filter.Header className="text-[18px] font-bold" />
<Filter.Modal pos="left">
{courseList.map(course => (
<Filter.Item key={course.id} item={course} />
))}
</Filter.Modal>
</Filter>
<div className="flex gap-[16px]">
<Filter value={sortType} onChange={setSortType}>
<Filter.Header />
<Filter.Modal>
{sort.map(item => (
<Filter.Item key={item.id} item={item} />
))}
</Filter.Modal>
</Filter>
<Filter value={statusType} onChange={setStatusType}>
<Filter.Header />
<Filter.Modal>
{status.map(item => (
<Filter.Item key={item.id} item={item} />
))}
</Filter.Modal>
</Filter>
</div>

기존의 코드는 불필요하게 props를 넘겨준 것 같아서 Filter 컴포넌트를 리팩토링했다.

value에 들어가는 타입은 다음과 같다.

type valueType = { name: string; [key: string]: any };

이렇게 함으로써 가독성 좋게 코드를 작성할 수 있었다.


해결 해야하는 이슈

필터 modal을 여러 개 켜고 하나의 필터를 선택했을 때 다른 필터가 적용되는 이슈가 있다.

아마도 handleChange의 문제가 아닐까 싶다. 내일 빠르게 해결해야겠다.

앞으로 해야하는 것

  • 동영상 과제를 보여주는 기능 추가
  • 과제 테이블 위에 오름차순, 내림차순을 선택할 수 있도록 기능 추가
  • github workflow로 CI/CD 구현
  • 테스트 코드 작성
  • 반응형 UI

내일 할 일

  • 알고리즘 문제 풀이
  • 바닐라 JS로 리액트 만들기 스터디 진행
  • 익스텐션 개발
  • nest.js 강의 듣기
  • 쿠버네티스 강의 Kubernetes를 통한 클라우드 조정 듣기
  • 학습공동체 보고서 작성 후 제출